﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Reflection;
using Microsoft.Xna.Framework.Graphics;
using System.Xml.Linq;

namespace AL.Doodled
{

    /// <summary>
    /// This is a helper class for the Widget class
    /// that provides way to extract information.
    /// </summary>
    public static class DataExtractor
    {
        #region fields
        private static DoodledEngine engine;
        #endregion

        #region methods
        /// <summary>
        /// To be called from the doodled engine.
        /// </summary>
        /// <param name="inEngine">Should be this, by the doodled engine.</param>
        internal static void SetEngine(DoodledEngine inEngine)
        {
            engine = inEngine;
        }

        public static T TrySetFromStyle<T>(string key, Style style,
                                              Func<string, T> parser, T defaultVal)
        {
            if (style.IsAttributeDefined(key))
            {
                return parser(style[key]);
            }
            else
                return defaultVal;
        }

        /// <summary>
        /// Tries to set the value of the entered property to
        /// the value of the given key.
        /// </summary>
        /// <param name="prop">The property.</param>
        /// <param name="key">The dictionary key.</param>
        /// <param name="attributes">The dictionary the value should be given from.</param>
        public static string TrySetFromAttribute(string key,
            Dictionary<string, string> attributes)
        {
            if (attributes.ContainsKey(key))
                try
                {
                    return attributes[key];
                }
                catch (Exception e)
                {
                    throw new Exception(
                        "Unable to set the propertys value: " + e);
                }
            else
                return null;
        }

        /// <summary>
        /// Tries to set the value of the entered property to
        /// the value of the given key.
        /// </summary>
        /// <typeparam name="T">The propertys type.</typeparam>
        /// <param name="prop">The property.</param>
        /// <param name="key">The dictionary key.</param>
        /// <param name="attributes">The dictionary the value should be given from.</param>
        /// <param name="parser">
        /// A lambda expression that should be used to parse the
        /// value string from the dictionary.
        /// </param>
        public static T TrySetFromAttribute<T>(string key,
            Dictionary<string, string> attributes, Func<string, T> parser,
            T defaultval)
        {
            if (attributes.ContainsKey(key))
                try
                {
                    return parser(attributes[key]);
                }
                catch (Exception e)
                {
                    throw new Exception("Unable to set the propertys value: " + e);
                }
            else
                return defaultval;
        }

        public static int DIntParse(string nText, out Measure measure)
        {
            if (nText.Length > 0)
            {
                string data = nText.Trim();
                string n = nText.Replace("%", "");
                if (n.Length != data.Length)
                    measure = Measure.Percent;
                else
                    measure = Measure.Pixels;
                return int.Parse(n);
            }
            else
            {
                measure = Measure.Pixels;
                return 0;
            }

        }

        public static Color DColorParse(string cText)
        {
            Color color = Color.White;
            PropertyInfo[] colorProperties = typeof(Color).GetProperties(
                BindingFlags.Static | BindingFlags.Public);

            foreach (PropertyInfo info in colorProperties)
            {
                if (info.Name == cText)
                {
                    color = (Color)info.GetValue(null, null);
                    break;
                }
            }

            return color;
        }

        public static SpriteFont DFontParse(string fText)
        {
            string data = fText == "" ? "default" :  fText;

            if (engine.IsFontDefined(data))
                return engine.GetFont(data);
            else
                return null;
        }

        public static Texture2D DTextureParse(string tText)
        {
            string data = tText == "" ? "default" : tText;

            if (engine.IsTextureDefined(data))
                return engine.GetTexture(data);
            else
                return null;
        }

        public static Widget WidgetParse(XElement element)
        {
            return engine.Compiler.CompileWidget(element);
        }

        public static Widget WidgetParse(string element)
        {
            XElement ele = XElement.Parse(
                engine.Compiler.RegisterCompile(element));

            return engine.Compiler.CompileWidget(ele);
        }
        #endregion
    }
}
